package com.rankeiot.developer.controller;

import cn.hutool.core.util.IdUtil;
import com.rankeiot.core.Current;
import com.rankeiot.core.anno.Auth;
import com.rankeiot.core.data.response.Resp;
import com.rankeiot.core.inner.argumet.QueryPage;
import com.rankeiot.core.sqltoy.Sql;
import com.rankeiot.core.util.CollectionUtil;
import com.rankeiot.core.util.IDUtil;
import com.rankeiot.core.util.StringUtil;

import com.rankeiot.developer.DevelopMenu;
import com.rankeiot.developer.domain.TableFieldMeta;
import com.rankeiot.developer.domain.TableMeta;
import com.rankeiot.developer.service.TableServices;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.sagacity.sqltoy.config.model.PKStrategy;
import org.sagacity.sqltoy.dao.LightDao;
import org.sagacity.sqltoy.model.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.ssssssss.magicapi.core.service.MagicResourceService;
import org.ssssssss.magicapi.datasource.model.DataSourceInfo;
import org.ssssssss.magicapi.datasource.model.MagicDynamicDataSource;
import org.ssssssss.magicapi.datasource.service.DataSourceMagicDynamicRegistry;

import java.sql.*;
import java.util.*;

@Auth(DevelopMenu.TABLEMETA)
@RestController
@RequestMapping("tableMeta")
@RequiredArgsConstructor
public class TableMetaController {
    private final DataSourceMagicDynamicRegistry dataSourceMagicDynamicRegistry;
    private final LightDao dao;
    private final TableServices tableServices;

    @PostMapping("dataSources")
    public Resp dataSources() {
        List<Map> result = new ArrayList<>();
        //添加默认数据源
        result.add(CollectionUtil.asMap("key", "default", "title", "默认数据源"));
        List<DataSourceInfo> dsList = dataSourceMagicDynamicRegistry.mappings().stream().distinct().toList();
        for (DataSourceInfo dsi : dsList) {
            Map item = new HashMap();
            item.put("key", dsi.getKey());
            item.put("title", dsi.getName());
            item.put("id",dsi.getId());
            item.put("lock",dsi.getLock());
            result.add(item);
        }
        return Resp.of(result);
    }


    /**
     * 新增表信息
     */
    @Operation(summary = "新增表信息")
    @Auth(DevelopMenu.TABLEMETA_ADD)
    @PostMapping("add")
    public Resp add(@Valid @RequestBody TableMeta tableMeta) {
        tableServices.add(tableMeta);
        return Resp.of(tableMeta.getId());
    }


    /**
     * 删除表信息
     */
    @Operation(summary = "删除表信息")
    @Auth(DevelopMenu.TABLEMETA_DELETE)
    @Transactional
    @PostMapping("delete")
    public Resp delete(@RequestParam String id) {
        tableServices.delete(id);
        return Resp.ok();
    }

    /**
     * 更新表信息
     */
    @Operation(summary = "更新表信息")
    @Auth(DevelopMenu.TABLEMETA_EDIT)
    @PostMapping("save")
    public Resp save(@Valid @RequestBody TableMeta tableMeta) {
        tableServices.save(tableMeta);
        return Resp.ok();
    }

    /**
     * 获取表信息
     */
    @Operation(summary = "获取表信息详细")
    @Auth(DevelopMenu.TABLEMETA)
    @GetMapping("detail")
    public Resp<TableMeta> detail(String id) {
        TableMeta tableMeta = tableServices.detail(id).getMeta();
        return Resp.of(tableMeta);
    }

    /**
     * 获取表信息列表
     */
    @Operation(summary = "列出表信息")
    @Auth(DevelopMenu.TABLEMETA)
    @PostMapping("list")
    public Resp<TableMeta> list(QueryPage query) {
        String sql = Sql.select("*")
                .from(TableMeta.TABLE)
                .optional(q -> q
                        .eq(TableMeta.Fields.tableName)
                        .eq(TableMeta.Fields.fieldsMeta)
                        .eq(TableMeta.Fields.crateTime)
                        .eq(TableMeta.Fields.createUser)
                ).orderByDesc(TableMeta.Fields.id)
                .toString();
        Page result = dao.findPage(query.page(), sql, query.params(), TableMeta.class);
        return Resp.of(result);
    }

    @Operation(summary = "检查表模型对应的数据库表是否存在")
    @Auth(DevelopMenu.TABLEMETA_GEN_TABLE)
    @PostMapping("checkTable")
    public Resp checkTable(String id) {
        return Resp.of(tableServices.checkTable(id));
    }

    @Auth(DevelopMenu.TABLEMETA_GEN_TABLE)
    @PostMapping(value = "genTable")//,produces={"text/event-stream"})
    public Resp genTable(String id) {
        tableServices.gentTable(id, true);
        return Resp.ok();
    }
    @Auth(DevelopMenu.TABLEMETA_EDIT)
    @PostMapping(value = "importFieldsFromTable")
    public Resp importFieldsFromTable(String dataSource, String tableName) {
        if (StringUtil.isEmpty(tableName)) {
            Resp.fail("表名不能为空");
        }
        try (Connection conn = tableServices.getConnection(dataSource)) {
            DatabaseMetaData meta = conn.getMetaData();
            String catalog = conn.getCatalog();
            String schema = conn.getSchema();
            ResultSet tbRs = meta.getTables(catalog, schema, tableName, new String[]{"TABLE", "VIEW"});
            String tableType = "TABLE";
            if (tbRs.next()) {
                tableType = tbRs.getString("TABLE_TYPE");
            } else {
                tbRs.close();
                Resp.fail("数据库中没有表 '" + tableName + "'");
            }
            tbRs.close();
            List<TableFieldMeta> columns = new ArrayList<>();
            if ("VIEW".equals(tableType)) {
                Statement stm = conn.createStatement();
                ResultSet rs = stm.executeQuery("select * from " + tableName + " where 0");
                ResultSetMetaData rm = rs.getMetaData();
                int c = rm.getColumnCount();
                for (int i = 1; i <= c; i++) {
                    TableFieldMeta dc = new TableFieldMeta();
                    dc.setColumnName(rm.getColumnName(i));
                    dc.setPrimaryKey(false);
                    //  dc.setDataType(rm.getColumnTypeName(i));
                    dc.setLength(rm.getColumnDisplaySize(i));
                    dc.setScale(rm.getScale(i));
                    dc.setVisibleInForm(true);
                    dc.setVisibleInList(true);
                    int dataType = rm.getColumnType(i);
                    //  setType(dataType,dc);
                    dc.setType(dataType);
                    dc.setNativeType(tableServices.getSqlDataType(dataType));
                    dc.setTitle(rm.getColumnLabel(i));
                    dc.setMandatory(false);
                    dc.setSearchCondition(false);
                    columns.add(dc);
                    // dm.getColumns().add(dc);
                }
                rs.close();
            } else {
                //主键
                Set<String> primaryKeys = new HashSet<>();//dm.getPrimaryKeys();
                ResultSet rs = meta.getPrimaryKeys(catalog, schema, tableName);
                while (rs.next()) {
                    String cn = rs.getString("COLUMN_NAME");
                    primaryKeys.add(cn);
                }
                ResultSet colMetaRs = null;
                try {
                    colMetaRs = meta.getColumns(catalog, schema, tableName, "%");
                    ResultSetMetaData rm = colMetaRs.getMetaData();
                    int columnCount = rm.getColumnCount();
                    while (colMetaRs.next()) {
                        TableFieldMeta dc = new TableFieldMeta();
                        String cn = colMetaRs.getString("COLUMN_NAME");
                        dc.setColumnName(cn);
                        dc.setPrimaryKey(primaryKeys.contains(cn));
                        dc.setLength(colMetaRs.getInt("COLUMN_SIZE"));
                        dc.setScale(colMetaRs.getInt("DECIMAL_DIGITS"));
                        dc.setVisibleInForm(true);
                        dc.setVisibleInList(true);
                        if (colMetaRs.getBoolean("IS_AUTOINCREMENT")) {
                            dc.setStrategy(PKStrategy.IDENTITY);
                        }
                        int dataType = colMetaRs.getInt("DATA_TYPE");
                        dc.setType(dataType);
                        dc.setNativeType(tableServices.getSqlDataType(dataType));
                        dc.setTitle(colMetaRs.getString("REMARKS"));
                        if (StringUtil.isEmpty(dc.getTitle())) {
                            dc.setTitle(cn);
                        }
                        dc.setMandatory(!"YES".equals(colMetaRs.getString("IS_NULLABLE")));
                        if (!dc.isPrimaryKey() && dc.isMandatory()) {//默认非空字段作为搜索项
                            dc.setSearchCondition(true);
                        }
                        columns.add(dc);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (colMetaRs != null) {
                        colMetaRs.close();
                    }
                }
            }
            return Resp.of(columns);
        } catch (SQLException e) {
            e.printStackTrace();
            Resp.fail(e.getMessage());
        }
        return Resp.ok();
    }
}
